import java.util.Random;

public class TestIntMatrixMultiplication {
	public static int getPotDe2MasCercana(int n){
		return (int)Math.ceil((Math.log10(n)/Math.log10(2)));	
	}
	
	public static int[][] completarMatriz(int[][] matriz,int k){
		
		int n = getPotDe2MasCercana(k);
		n = (int)Math.pow(2, n); 
		
		int[][] nueva = new int[n][n];
		for (int i = 0; i < matriz.length; i++) {
			for (int j = 0; j < matriz.length; j++) {
				nueva[i][j] = matriz[i][j];
			}
		}
		return nueva;
	}
    public static void main (String...args) throws Exception {
         int n = args.length > 0 ? Integer.parseInt(args[0]) : 5;
        final int seed = args.length > 1 ? Integer.parseInt(args[1]) : 128;
        final Random random = new Random(seed);

        int[][] a, b, c,d,a2,b2,c2,d2;
       
        a = new int[n][n];
        b = new int[n][n];
        c = new int[n][n];
        d = new int[n][n];
        
        
        for(int i=0; i<n; i++) {
            for(int j=0; j<n; j++) {
                a[i][j] = random.nextInt(16)%2==0?1:0;
                b[i][j] = a[i][j];//random.nextInt(16)%2==0?1:0;
            }
        }
        
        a2 = completarMatriz(a, n);
        b2 = completarMatriz(b, n);
        c2 = completarMatriz(c, n);
        d2 = completarMatriz(d, n);
        
        IntMatrixMultiplication classical = new ClassicMatrixMultiplication();
        IntMatrixMultiplication strassen1 = new Strassen1MatrixMultiplication();
        IntMatrixMultiplication strassen2 = new Strassen2MatrixMultiplication();

        System.out.println("n = " + n);

        if (a.length < 64) {
            System.out.println("A");
            dumpMatrix(a2);
            System.out.println("B");
            dumpMatrix(b2);
            System.out.println("classic");
            classical.mult(c2, a2, b2);
            dumpMatrix(c2);
            System.out.println("strassen");
            d2 = strassen1.mult(d2, a2, b2);
            dumpMatrix(d2);
            
            boolean aux = true;
            for (int i = 0; i < d2.length; i++) {
				for (int j = 0; j < d2.length; j++) {
					if(d2[i][j]!=c2[i][j]){
						aux = false;
						System.out.println("LAS MATRICES NO SON IGUALES!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
						break;
					}
					
				}
				if(!aux){
					break;
				}
			}
            
        

            return;
        }

        for (int i = 0; i < 5; ++i) {
            timeMultiplies(classical, a, b, c);
            if (n <= 256)
                timeMultiplies(strassen1, a, b, c);
            
            //timeMultiplies(strassen2, a, b, c);
        }
    }

    static void timeMultiplies (IntMatrixMultiplication algorithm, int[][] a, int[][] b, int[][] c) {
        final long start = System.currentTimeMillis();
        algorithm.mult(c, a, b);
        final long finish = System.currentTimeMillis();
        System.out.println(algorithm.getName() + " took " + (finish - start) + "ms");
    }

    static void dumpMatrix (int[][] m) {
        for (int[] row : m) {
            System.out.print("[\t");
            for (int val : row) {
                System.out.print(val);
                System.out.print('\t');
            }
            System.out.println(']');
        }
    }
}
